using System;
using System.Collections.Generic;
using System.Text;

namespace TinyOsMessageForwarder
{
    public class TinyOS2Message
    {
        public static readonly int MAX_LENGTH = 28;
        public const UInt16 BROADCAST_ADDRESS = 0xFFFF;

        private byte[] message;

        public byte[] RawMessage
        {
            get { return message; }
            //    set { message = value; }
        }

        //        byte ptr;
        public TinyOS2Message()
        {
            message = new byte[7 + MAX_LENGTH];
        }

        public TinyOS2Message(byte[] rawMessage)
        {
            message = rawMessage; //TODO: check length, ...
        }

        public UInt16 AddressDst
        {
            get
            {
                return ReadUInt16BigEndian(0);
            }
            set
            {
                WriteUInt16BigEndian(0, value);
            }
        }

        public UInt16 AddressSrc
        {
            get
            {
                return ReadUInt16BigEndian(2);
            }
            set
            {
                WriteUInt16BigEndian(2, value);
            }
        }

        public byte AMType
        {
            get
            {
                return ReadUInt8(6);
            }
            set
            {
                WriteUInt8(6, value);
            }
        }

        public byte Group
        {
            get
            {
                return ReadUInt8(5);
            }
            set
            {
                WriteUInt8(5, value);
            }
        }

        public byte Length
        {
            get
            {
                return ReadUInt8(4);
            }
            set
            {
                WriteUInt8(4, value);
            }
        }


        public void ResetData()
        {
            //            ptr = 5;
        }

        protected void WriteUInt8(byte offset, byte x)
        {
            message[offset] = x;
        }

        protected byte ReadUInt8(byte offset)
        {
            return message[offset];
        }

        protected void WriteUInt16(byte offset, UInt16 x)
        {
            message[offset] = (byte)(x & 0xFF);
            message[offset + 1] = (byte)((x >> 8) & 0xFF);
        }

        protected void WriteUInt16BigEndian(byte offset, UInt16 x)
        {
            message[offset+1] = (byte)(x & 0xFF);
            message[offset] = (byte)((x >> 8) & 0xFF);
        }

        protected UInt16 ReadUInt16(byte offset)
        {
            return (UInt16)(message[offset] + (((UInt16)(message[offset + 1])) << 8));
        }

        protected Int16 ReadInt16(byte offset)
        {
            return (Int16)((UInt16)message[offset] + (((UInt16)(message[offset + 1])) << 8));
        }

        protected UInt16 ReadUInt16BigEndian(byte offset)
        {
            return (UInt16)(message[offset+1] + (((UInt16)(message[offset])) << 8));
        }

        protected void WriteUInt32(byte offset, UInt32 x)
        {
            message[offset] = (byte)(x & 0xFF);
            message[offset + 1] = (byte)((x >> 8) & 0xFF);
            message[offset + 2] = (byte)((x >> 16) & 0xFF);
            message[offset + 3] = (byte)((x >> 24) & 0xFF);
        }

        protected UInt32 ReadUInt32(byte offset)
        {
            return ReadUInt16(offset) + (((UInt32)ReadUInt16((byte)(offset + 2))) << 16);
        }

        public string ToRawString()
        {
            StringBuilder sb = new StringBuilder();
            for (int i=0; i< Length; i++)
                sb.Append(message[i]+" ");
            return sb.ToString();
        }
    }
}

